package com.guangfeng.yql.comm.netty.util;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import lombok.SneakyThrows;
import org.bytedeco.ffmpeg.avcodec.AVPacket;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.ffmpeg.global.avutil;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;

import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;

public class RtspPullUtils {

    @SneakyThrows
    public static void pull(FFmpegFrameGrabber grabber, ChannelHandlerContext context) {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        grabber.start();
        boolean b = supportFlvFormatCodec(grabber);
        FFmpegFrameRecorder recorder = createTransterOrRecodeRecorder(bos, grabber);
        while (!grabber.isCloseInputStream()) {
            AVPacket packet = grabber.grabPacket();
            if (packet == null) {
                grabber.start();
                continue;
            }
            ByteBuffer byteBuffer = packet.asByteBuffer();
            bos.write(byteBuffer.array());
            context.writeAndFlush(Unpooled.wrappedBuffer(bos.toByteArray()));
        }
    }

    /**
     * 创建转码推流录制器
     *
     * @return
     */
    protected static FFmpegFrameRecorder createTransterOrRecodeRecorder(ByteArrayOutputStream bos, FFmpegFrameGrabber grabber) {
        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(bos, grabber.getImageWidth(), grabber.getImageHeight(),
                grabber.getAudioChannels());
        recorder.setFormat("flv");
        // 转码
        recorder.setInterleaved(false);
        recorder.setVideoOption("tune", "zerolatency");
        recorder.setVideoOption("preset", "ultrafast");
        recorder.setVideoOption("crf", "26");
        recorder.setVideoOption("threads", "1");
        recorder.setFrameRate(25);// 设置帧率
        recorder.setGopSize(25);// 设置gop,与帧率相同，相当于间隔1秒chan's一个关键帧
//			recorder.setVideoBitrate(500 * 1000);// 码率500kb/s
//			recorder.setVideoCodecName("libx264");	//javacv 1.5.5无法使用libx264名称，请使用下面方法
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
        recorder.setPixelFormat(avutil.AV_PIX_FMT_YUV420P);
        recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);
//			recorder.setAudioCodecName("aac");
        recorder.setOption("keyint_min", "25");    //gop最小间隔

        /**
         * 启用RDOQ算法，优化视频质量 1：在视频码率和视频质量之间取得平衡 2：最大程度优化视频质量（会降低编码速度和提高码率）
         */
        recorder.setTrellis(1);
        recorder.setMaxDelay(0);// 设置延迟
        return recorder;
    }

    /**
     * 是否支持flv的音视频编码
     *
     * @return
     */
    private static boolean supportFlvFormatCodec(FFmpegFrameGrabber grabber) {
        int audioChannels = grabber.getAudioChannels();
        int vcodec = grabber.getVideoCodec();
        int acodec = grabber.getAudioCodec();
        return (avcodec.AV_CODEC_ID_H264 == vcodec
                || avcodec.AV_CODEC_ID_H263 == vcodec) && (audioChannels == 0 || avcodec.AV_CODEC_ID_AAC == acodec || avcodec.AV_CODEC_ID_AAC_LATM == acodec);
    }

}
